package com.sharelords.biz.common;

import com.sharelords.biz.util.BizQueryUtil;
import com.sharelords.biz.util.BizQueryUtil.Impl;
import com.sharelords.biz.util.InvokeUtil;
import com.sharelords.biz.util.ObjectClassInvoke;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.entity.Example.Criteria;

import javax.persistence.Id;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;

/**
 * @param <Bo>
 * @param <Entity>
 * @param <D>
 * @param <Dao>
 * @author 千古龙少
 * @Description: 通用biz层工具
 * @date 2019年8月12日 下午5:17:47
 */
public class BaseBizImpl<Bo, Entity, D, Dao extends Mapper<Entity>> implements BaseBiz<Bo, D> {

    // 用于查询
    protected BizQueryUtil<Bo, Entity> queryUtil;

    private Class<Bo> boClass;
    private Class<Entity> entityClass;
    private String primaryKeyName;

    @Autowired
    private Dao dao;

    @SuppressWarnings("unchecked")
    public BaseBizImpl() {
        // 得到父类的泛型
        Type sType = getClass().getGenericSuperclass();
        // 得到实际的类型参数数组
        Type[] generics = ((ParameterizedType) sType).getActualTypeArguments();
        // 得到第一个泛型的Class
        boClass = (Class<Bo>) generics[0];
        // 得到第二个泛型的Class
        entityClass = (Class<Entity>) generics[1];
        // 查询工具
        this.queryUtil = new BizQueryUtil<>(this.boClass, this.entityClass);
        // 主键字段名称
        this.primaryKeyName = ObjectClassInvoke.getFieldNameOfAno(entityClass, Id.class);
    }

    @Override
    public Integer save(Bo bo) {
        if (bo == null) {
            return 0;
        }

        Entity entity = InvokeUtil.copy(bo, entityClass);

        // 执行新增
        int saveCount = dao.insert(entity);

        // 参数重新赋值（为了返回主键）
        BeanUtils.copyProperties(entity, bo);

        return saveCount;
    }

    @Override
    public Integer saveSelective(Bo bo) {
        if (bo == null) {
            return 0;
        }

        Entity entity = InvokeUtil.copy(bo, entityClass);

        // 执行新增
        int saveCount = dao.insertSelective(entity);

        // 参数重新赋值（为了返回主键）
        BeanUtils.copyProperties(entity, bo);

        return saveCount;
    }

    @Override
    public Integer update(Bo bo) {
        if (bo == null) {
            return 0;
        }

        return dao.updateByPrimaryKey(InvokeUtil.copy(bo, entityClass));
    }

    @Override
    public Integer updateSelective(Bo bo) {
        if (bo == null) {
            return 0;
        }

        return dao.updateByPrimaryKeySelective(InvokeUtil.copy(bo, entityClass));
    }

    @Override
    public Integer deletePhysically(D d) {
        if (d == null) {
            return 0;
        }

        return dao.deleteByPrimaryKey(d);
    }

    @Override
    public Bo queryByPrimaryKey(D d) {
        if (d == null) {
            return null;
        }

        Entity entity = dao.selectByPrimaryKey(d);
        return InvokeUtil.copy(entity, boClass);
    }

    @Override
    public List<Bo> queryByBo(Bo bo) {
        if (bo == null) {
            return Collections.emptyList();
        }

        List<Entity> entityList = dao.select(InvokeUtil.copy(bo, entityClass));
        return InvokeUtil.copyList(entityList, boClass);
    }

    @Override
    public List<Bo> queryAll() {
        List<Entity> entityList = dao.selectAll();
        return InvokeUtil.copyList(entityList, boClass);
    }

    @Override
    public List<Bo> queryReCordsByIdList(final List<D> idList) {
        if (idList == null || idList.isEmpty()) {
            return Collections.emptyList();
        }

        return queryUtil.queryMore(this.dao, new Impl() {
            @Override
            public Example impl(Example example, Criteria criteria) {
                criteria.andIn(primaryKeyName, idList);
                return example;
            }
        });
    }

    @Override
    public Integer queryCountByBo(Bo bo) {
        if (bo == null) {
            return 0;
        }

        return this.dao.selectCount(InvokeUtil.copy(bo, entityClass));
    }

}
